package com.masonluo.mlonlinejudge.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.masonluo.mlonlinejudge.dao.ResultRepository;
import com.masonluo.mlonlinejudge.dao.SolutionRepository;
import com.masonluo.mlonlinejudge.dao.UserInfoRepository;
import com.masonluo.mlonlinejudge.entity.Result;
import com.masonluo.mlonlinejudge.entity.Role;
import com.masonluo.mlonlinejudge.entity.Solution;
import com.masonluo.mlonlinejudge.entity.UserInfo;
import com.masonluo.mlonlinejudge.model.bo.UserInfoBo;
import com.masonluo.mlonlinejudge.model.param.ResultFindParam;
import com.masonluo.mlonlinejudge.model.vo.ResultVo;
import com.masonluo.mlonlinejudge.service.ResultService;
import com.masonluo.mlonlinejudge.service.RoleService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;

/**
 * @author masonluo
 * @date 2021/3/12 11:45 下午
 */
@Service
public class ResultServiceImpl implements ResultService {

    @Autowired
    private ResultRepository resultRepository;
    @Autowired
    private SolutionRepository solutionRepository;
    @Autowired
    private RoleService roleService;
    @Autowired
    private UserInfoRepository userInfoRepository;

    @Override
    public Result findResultById(Integer id) {
        return resultRepository.selectById(id);
    }

    @Override
    public Page<ResultVo> findResultByProblem(Integer userId, Integer problemId, Integer testId, Integer current, Integer limit) {

        QueryWrapper<Result> queryWrapper = new QueryWrapper();
        List<Integer> resultList = resultRepository.queryResultIdListByProblemId(problemId,userId,testId);
        if (resultList.size()==0){
            resultList.add(-2);
        }
        queryWrapper.in("id",resultList);
        queryWrapper.orderByDesc("updated_time");
        //默认页面尺寸和当前页数
        Integer pageNum = 1;
        Integer pageSize = 10;
        if (null != current) {
            pageNum = current;
        }
        if (null != limit) {
            pageSize = limit;
        }
        Page<ResultVo> resultVoPage = resultPageTurnToResultVoPage(queryWrapper, pageNum, pageSize);
        return resultVoPage;
    }


    @Override
    public  Page<ResultVo> findResultAll(ResultFindParam param) {

        QueryWrapper<Result> queryWrapper = new QueryWrapper();
        List<Integer> resultList = new ArrayList<>();
        Date date = new Date();
        if (param.getStartTime() == null && param.getEndTime() == null){
            param.setStartTime(addDayOfDate(date,-3));
            param.setEndTime(date);
        } else if (param.getStartTime()==null){
            param.setStartTime(addDayOfDate(param.getEndTime(),-3));
        } else if (param.getEndTime()==null){
            param.setEndTime(addDayOfDate(param.getStartTime(),3));
        }

        // 判断发起查询的用户身份
        Role role = roleService.findByUserId(param.getUserId());

        // 判断为学生
        if (role.getName().equals("student")){
            // 查询的resultId均在startTime,endTime中间
            resultList = resultRepository.queryResultListByUserId(param.getUserId(),param.getStartTime(),param.getEndTime());
            if (resultList.isEmpty()){
                resultList.add(-1);
            }
        }
        // 判断为老师或学校管理员
        else if (role.getName().equals("teacher") || role.getName().equals("schoolAdmin")){
                // 如果nickName不为空,获取like nickName的历史记录;为空则返回该学校的历史记录
                // 查询的resultId均在startTime,endTime中
                if (param.getSchoolId() == null){
                    throw new IllegalArgumentException("需要传入学校id");
                }
                resultList = resultRepository.queryResultListBySchoolIdAndNickName(param.getSchoolId(),param.getNickname(),param.getStartTime(),param.getEndTime());
                if (resultList.isEmpty()){
                    resultList.add(-1);
                }
        }
        // 超级管理员
        else {
            resultList = resultRepository.queryResultListBySchoolIdAndNickName(param.getSchoolId(),param.getNickname(),param.getStartTime(),param.getEndTime());
            if (resultList.isEmpty()){
                resultList.add(-1);
            }
        }

        if (resultList.size()!=0){
            queryWrapper.in("id",resultList);
        }else{
            queryWrapper.between("created_time",param.getStartTime(),param.getEndTime());
        }

        // 排序
        queryWrapper.orderByDesc("updated_time");

        //默认页面尺寸和当前页数
        Integer pageNum = 1;
        Integer pageSize = 10;
        if (null != param.getCurrentPage()) {
            pageNum = param.getCurrentPage();
        }
        if (null != param.getPageSize()) {
            pageSize = param.getPageSize();
        }
        return resultPageTurnToResultVoPage(queryWrapper, pageNum, pageSize);
    }

    @Override
    public List<Result> listAll() {
        List<Result> results;
        results = resultRepository.listAll();
        return results == null ? Collections.emptyList() : results;
    }

    @Override
    public String findResourceCodeByResultId(Integer resultId) {
        if (resultId.equals(-1)){
            return null;
        }
        String sourceCode = solutionRepository.findSourceCodeByResultId(resultId);
        return sourceCode;
    }

    private Page<ResultVo> resultPageTurnToResultVoPage(QueryWrapper<Result> queryWrapper, Integer pageNum, Integer pageSize) {
        Page<Result> resultPage = resultRepository.selectPage(new Page<Result>(pageNum, pageSize), queryWrapper);
        Page<ResultVo> resultVoPage = new Page<>();
        resultVoPage.setCurrent(resultPage.getCurrent());
        resultVoPage.setTotal(resultPage.getTotal());
        resultVoPage.setCountId(resultPage.getCountId());
        resultVoPage.setPages(resultPage.getPages());
        resultVoPage.setMaxLimit(resultPage.getMaxLimit());
        resultVoPage.setOrders(resultPage.getOrders());
        resultVoPage.setSize(resultPage.getSize());
        List<ResultVo> resultVos = new ArrayList<>();
        for (Result res : resultPage.getRecords()) {
            UserInfo userInfo = resultRepository.queryUserInfoByResultId(res.getId());
            String problem_title = resultRepository.queryProblemTitleByResultId(res.getId());
            ResultVo resultVo = new ResultVo();
            resultVo.setId(res.getId());
            resultVo.setCreatedTime(res.getCreatedTime());
            resultVo.setUpdatedTime(res.getUpdatedTime());
            resultVo.setCompilerResult(res.isCompilerResult());
            resultVo.setProcessResult(res.getProcessResult());
            resultVo.setCpuTime(res.getCpuTime());
            resultVo.setErrorData(res.getErrorData());
            if(res.getMemory()!=null){
                int a = res.getMemory();
                resultVo.setMemory(a/1024/1024);
            }
            resultVo.setTestCaseIndex(res.getTestCaseIndex());
            resultVo.setUserAnswer(res.getUserAnswer());
            resultVo.setTrueAnswer(res.getTrueAnswer());
            if (userInfo != null){
                resultVo.setUserId(userInfo.getUserId());
                resultVo.setUserName(userInfo.getNickname());
            }
            if (problem_title != null){
                resultVo.setProblem_title(problem_title);
            }
            resultVos.add(resultVo);
        }
        resultVoPage.setRecords(resultVos);
        return resultVoPage;
    }

    private Date addDayOfDate(Date date,int i){
        Calendar c = Calendar.getInstance();
        c.setTime(date);
        c.add(Calendar.DATE, i);
        Date newDate = c.getTime();
        return newDate;
    }
}
